package com.shelpe.services.sinbad.controller;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.shelpe.services.sinbad.entity.jpa.Adgroup;
import com.shelpe.services.sinbad.model.RptKeyword;
import com.shelpe.services.sinbad.model.RptKeywordParam;
import com.shelpe.services.sinbad.repository.jpa.AdgroupRepository;
import com.shelpe.services.sinbad.service.KeywordService;
import com.shelpe.services.sinbad.service.KeywordsLogService;
import com.shelpe.services.sinbad.service.RptKeywordService;
import com.shelpe.services.sinbad.service.SemiautoService;
import com.shelpe.services.sinbad.service.UserService;
import com.shelpe.services.sinbad.service.simbaproxy.SemiautoClient;
import com.shelpe.services.sinbad.service.simbaproxy.SemiautoClient.Keyword;
import com.shelpe.services.sinbad.service.simbaproxy.SemiautoClient.KeywordsDto;
import com.shelpe.services.sinbad.service.simbaproxy.SemiautoClient.SemiautoDto;
import com.shelpe.services.sinbad.service.simbaproxy.SimbaProxy;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@Getter
@Setter
@RequestMapping("/sinbadservice")
public class SemiautoController {

	@Autowired
	KeywordService keywordService;

	@Autowired
	SemiautoService semiautoService;
	
	@Autowired
	SemiautoClient semiautoClient;

	@Autowired
	SimbaProxy simbaProxy;

	@Autowired
	UserService userService;
	
	@Autowired
	RptKeywordService rptKeywordService;
	
	@Autowired
	KeywordsLogService keywordsLogService; 
	
	@Autowired
	private AdgroupRepository adgroupRepository;
	
	@RequestMapping("/logs/{keywordId}")
	public @ResponseBody boolean selectByToday(@PathVariable("keywordId")Long keywordId){
		boolean ret = false;
		try {
			ret = keywordsLogService.selectSemiautoExecByToday(keywordId);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return ret;
	}
	
	@RequestMapping(method = RequestMethod.GET, value = "/nick")
	public @ResponseBody String getNick(Long userId){
		return userService.getNick(userId);
	}
	
	@RequestMapping(method = RequestMethod.POST, value = "/updateByKeyword")
	public @ResponseBody int update(@RequestBody com.shelpe.services.sinbad.model.Keyword keyword, @RequestParam Long userId){
		return keywordService.update(keyword, userId);
	}

	@RequestMapping("/userid")
	public @ResponseBody Long getUserId(Long semiautoId){
		return semiautoService.getUserId(semiautoId);
	}
	
	@RequestMapping("/semiautos/{semiautoId}/adgroups/{adgroupId}/keywords")
	public @ResponseBody KeywordsDto convert(@PathVariable("semiautoId")Long semiautoId, @PathVariable("adgroupId")Long adgroupId, 
			@RequestParam(required = false)Long userId, 
			@RequestParam(required = false)String keywordIds, 
			@RequestParam(required=false)boolean matched){
		if(userId==null){
			userId = semiautoService.getUserId(semiautoId);
		}
		log.info("userId:{}", userId);
		SemiautoDto semiautoDto = semiautoClient.findSemiauto(semiautoId);
		List<com.shelpe.services.sinbad.model.Keyword> words = keywordService.getKeywords(userId, adgroupId.toString(), null);
		return convert(semiautoDto, adgroupId, userId, words, keywordIds, matched);
	}
	
	@RequestMapping("/adgroupids")
	public @ResponseBody List<Long> adgroupids(String adgroupId, String campaignId){
		return getAdgroupIds(adgroupId, campaignId);
	}
	
	private List<Long> getAdgroupIds(String adgroupId, String campaignId){
		List<Long> adgroupIds = new ArrayList<Long>();
		log.info("getAdgroupIds params adgroupId:{} campaignId:{}", adgroupId, campaignId);
		if(adgroupId!=null){
			for(String adgroupid : adgroupId.split(",")){
				adgroupIds.add(Long.valueOf(adgroupid));
			}
		}
		if(campaignId!=null){
			for(String campaignid : campaignId.split(",")){
				List<Adgroup> groups = adgroupRepository.findByCampaignID(Long.valueOf(campaignid));
				for(Adgroup group : groups){
					adgroupIds.add(group.getAutoID());
				}
			}
		}
		if(log.isInfoEnabled()){
			log.info("adgroupIds:{}", adgroupIds.toString());
		}
		return adgroupIds;
	}
	
	/**
	 * @param array
	 * @return
	 */
	private List<String> toList(String[] array){
		List<String> list = new ArrayList<String>();
		for(String obj : array){
			list.add(obj);
		}
		return list;
	}
	
	private Float getAvgCtr(Long userId, Long adgroupId, int day, int device){
		RptKeywordParam param = null;
		param = new RptKeywordParam();
		param.setUserId(userId);
		param.setAdgroupId(adgroupId);
		param.setDay(day);
		log.info("getAvgCtr param:{}", param.toString());
		switch (device) {
		case 1://移动思路,查PC平台的 
			param.setSource((byte)2);
			break;
		case 2:
			param.setSource((byte)1);
			break;
		}
		Float avgCtr = rptKeywordService.getAvgCtr(param);
		return avgCtr;
	}

	/**
	 * 是否需要删除  根据roi、ctr判断 
	 * @param userId 用户Id
	 * @param adgroupId 推广组Id
	 * @param day 思路数据天数
	 * @param device pc(2)/mobile(1)
	 * @param avgCtr
	 * @param keywordId
	 * @return
	 */
	private boolean isDel(Long userId, Long adgroupId, int day, int device, Float avgCtr, Long keywordId){
		boolean ret = true;
		RptKeywordParam param = null;
		param = new RptKeywordParam();
		param.setUserId(userId);
		param.setKeywordId(keywordId);
		param.setDay(day);
		switch (device) {
		case 1://移动思路,查PC平台的 
			param.setSource((byte)2);
			break;
		case 2:
			param.setSource((byte)1);
			break;
		}
		RptKeyword rptKeyword = rptKeywordService.getCtrAndRoi(param);
		if(rptKeyword!=null){
			if(rptKeyword.getRoi()>0){
				if(rptKeyword.getCtr() > 1.2*avgCtr){
					ret = false;
				}
			}
		}
		return ret;
	}
	private KeywordsDto convert(SemiautoDto semiautoDto, Long adgroupId, Long userId, List<com.shelpe.services.sinbad.model.Keyword> words, String keywordIds, boolean matched){
		KeywordsDto dto = new KeywordsDto();
		dto.setAdgroupID(adgroupId);
		Adgroup adgroup = adgroupRepository.findOne(adgroupId);
		List<Keyword> keywords = new ArrayList<Keyword>();
		Keyword keyword;
		List<String> ignoreIds = new ArrayList<String>();
		if(keywordIds!=null){
			ignoreIds = toList(keywordIds.split(","));
		}

		Float avgCtr = 0f;
		if(semiautoDto.getSettings().getDeleteModel()!=null){
			if(semiautoDto.getSettings().getDeleteModel().getStatus()==1){
				avgCtr = getAvgCtr(userId, adgroupId, semiautoDto.getSettings().getDate(), semiautoDto.getDevice());
			}
		}
		
		RptKeywordParam param = null;
		param = new RptKeywordParam();
		param.setUserId(userId);
		param.setDay(semiautoDto.getSettings().getDate());
		param.setSource((byte)semiautoDto.getDevice());
		
		for(com.shelpe.services.sinbad.model.Keyword word : words){
			if(!ignoreIds.contains(word.getKeywordId().toString())){
				keyword = new Keyword();
				if(log.isInfoEnabled()){
					log.info("word:{}", JSON.toJSONString(word));
				}
				
				param.setKeywordId(word.getKeywordId());
				
				RptKeyword rptKeyword = rptKeywordService.selectSum(param);
				if(log.isInfoEnabled()){
					log.info("rptKeyword:{}", JSON.toJSONString(rptKeyword));
				}
				BeanUtils.copyProperties(word, keyword);
				keyword.setMaxPrice(word.getMaxPrice());
				keyword.setMaxMobilePrice(word.getMaxMobilePrice());
				keyword.setMatchScope(word.getMatchscope());
				keyword.setKeywordID(word.getKeywordId());
				keyword.setMobileQscore(word.getWirelessQscore());
				keyword.setQscore(word.getQscore());
				keyword.setAsDefaultPrice(word.getIsDefaultPrice());
				keyword.setAsDefaultMobilePrice(word.getMobileIsDefaultPrice()==1?true:false);
				
				if(rptKeyword!=null){
					keyword.setClick(rptKeyword.getClick());
					keyword.setImpression(rptKeyword.getImpressions());
					keyword.setCvr(rptKeyword.getCvr());
					keyword.setCartCountRatio(rptKeyword.getCartCountRate());
					keyword.setFavCountRatio(rptKeyword.getFavCountRate());
					keyword.setProductRanking(rptKeyword.getAvgpos().intValue());
					keyword.setFavCount(rptKeyword.getFavItemCount()+rptKeyword.getFavShopCount());
					keyword.setPayCount(rptKeyword.getPayCount());
					keyword.setSale(rptKeyword.getSale());
					keyword.setRoi(rptKeyword.getRoi());
					keyword.setCpc(rptKeyword.getCpc());
					keyword.setCpm(rptKeyword.getCpm());
					keyword.setCartCount(rptKeyword.getCartTotal());
					keyword.setCost(rptKeyword.getCost());
					keyword.setClickRatio(rptKeyword.getCtr());
				}
				
				if(keyword.getMaxMobilePrice()==0){
					keyword.setMaxMobilePrice(keyword.getMaxPrice()*adgroup.getMobileDiscount()/100);
				}
				
				if(log.isInfoEnabled()){
					log.info("keyword:{}", JSON.toJSONString(keyword));
				}
				keywords.add(keyword);
			}else{
				log.info("需要删掉的:{}", word.getKeywordId());
			}
		}
		dto.setWords(keywords);
		if(log.isInfoEnabled()){
			log.info("调用算法之前的 keywords:{}", JSON.toJSONString(keywords));
		}
		KeywordsDto dto1 = semiautoClient.keywords(semiautoDto.getAutoID(), dto);
		if(log.isInfoEnabled()){
			log.info("调用算法之后的 keywords:{}", JSON.toJSONString(dto1.getWords()));
		}
		List<Keyword> ws1 = new ArrayList<Keyword>();
		
		List<Keyword> ws = dto1.getWords();
		for(Keyword w : ws){
			if(w.getMobilePrice()==0){
				w.setMobilePrice(w.getPrice()*adgroup.getMobileDiscount()/100);
			}
			
			w.setCpc(format(w.getCpc()));
			w.setCvr(format(w.getCvr()));
			w.setRoi(format(w.getRoi()));
			w.setClickRatio(format(w.getClickRatio()));
			w.setCartCountRatio(format(w.getCartCountRatio()));
			w.setFavCountRatio(format(w.getFavCountRatio()));
			try {
				w.setExecuted(keywordsLogService.selectSemiautoExecByToday(w.getKeywordID()));
			} catch (ParseException e) {
				log.error("select logs by today:{}", e.getMessage());
			}
			if(semiautoDto.getSettings().getDeleteModel().getStatus()==1){
				boolean del = isDel(userId, adgroupId, 
						semiautoDto.getSettings().getDate(),
						semiautoDto.getDevice(), avgCtr, w.getKeywordID());
				w.setDel(del);
			}
			
			if(matched){
				if(w.isMatched()){
					ws1.add(w);
				}
			}else{
				ws1.add(w);
			}
		}
		dto1.setWords(ws1);
		dto1.setAdgroup(adgroup);
		return dto1;
	}
	
	private float format(float in){
		DecimalFormat df = new DecimalFormat(".00");
		return Float.valueOf(df.format(in));
	}
	
	/**
	 * 将dtos转换为 出价API需要的字符串参数
	 * @param dtos
	 * @return
	 */
//	private List<String> toPriceParams(List<KeywordsDto> dtos, int device){
//		//[{"keywordId":"222886332274","maxPrice":88,"isDefaultPrice":0,"matchScope":4}]
//		JSONArray array = new JSONArray();
//		JSONObject obj;
//		
//		List<String> rets = new ArrayList<String>();
//		
//		for(KeywordsDto dto : dtos){
//			for(Keyword keyword : dto.getWords()){
//				if(keyword.isMatched()){
//					obj = new JSONObject();
//					obj.put("keywordId", keyword.getKeywordID());
//					if(device == 1){
//						obj.put("maxMobilePrice", keyword.getMobilePrice());//dto.getAdgroup().getMobileDiscount()*keyword.getPrice()/100
//						obj.put("mobileIsDefaultPrice", 0);//keyword.getAsDefaultMobilePrice()?1:0
//					}else if(device == 2){
//						obj.put("maxPrice", keyword.getPrice());
//						obj.put("isDefaultPrice", keyword.getAsDefaultPrice()?1:0);
//					}
//					obj.put("matchScope", keyword.getNewMatchScope());
//					array.add(obj);
//					if(array.size() > 50){
//						rets.add(array.toJSONString());
//						array.clear();
//					}
//				}
//			}
//			rets.add(array.toJSONString());
//		}
//		if(log.isInfoEnabled()){
//			for(String str : rets){
//				log.info("prices:{}", str);
//			}
//		}
//		return rets;
//	}
}
